﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using GameSchoolApplication.Models;
using GameSchoolApplication.Models.ViewModels;

namespace GameSchoolApplication.Repositories
{
    public class ExamRepository
    {
        gsDBDataContext link = new gsDBDataContext();

        /// <summary>
        /// Gets an exam by examID
        /// Precondition: ExamID must exist
        /// Postcondition: An exam has been returned
        /// Author: Aron modified by Alma
        /// Date: 04.05.2012
        /// </summary>
        public Exam getExamByID(int myExamID)
        {
            Exam myExam = (from e in link.Exams
                           where e.examID == myExamID
                           select e).First();
            return myExam;
        }

        /// <summary>
        /// Gets all exams for a course
        /// Precondition: Exams exist
        /// Postcondition: A list of exams is returned
        /// Author: Aron mod. by Alma 
        /// Date: 04.05. 2012
        /// </summary>
        public IQueryable<Exam> getExamsOfCourse(int courseID)
        {
            IQueryable<Exam> courseExams = (from e in link.Exams
                                              from cl in link.CourseLevels
                                              where cl.cID == courseID && e.lvlID == cl.lvlID
                                              select e);
            return courseExams;
        }
        /// <summary>
        /// Getting submitted exams
        /// Precondition: The user is a teacher and exams have been submitted
        /// Postcondition: A list of exams is returned
        /// Author: Aron mod. by Alma
        /// Date: 04.05. 2012
        /// </summary>
        public IQueryable<Exam> getUserExams(string userID)
        {
            IQueryable<Exam> myExams = (from e in link.Exams
                                       from cl in link.CourseLevels
                                       from s in link.StudentInClasses
                                       where s.stID == userID && s.cID == cl.cID && e.lvlID == cl.lvlID
                                       select e);
            return myExams; 
        }

        /// <summary>
        /// Getting all exams
        /// Precondition: Exams exist and user is a teacher/admin
        /// Postcondition: A list of all exams is returned
        /// Author: Aron mod. by Alma
        /// Date: 04.05. 2012
        /// </summary>
        public IQueryable<Exam> getAllExams()
        {
            return link.Exams;
        }

        /// <summary>
        /// Adds exam to database
        /// Precondition: The user is a teacher
        /// Postcondition: Exam has been added to database
        /// Author: Aron mod. by Alma
        /// Date: 4.5.12
        /// </summary>
        public int addExam(Exam myExam)
        {
            try
            {
                link.Exams.InsertOnSubmit(myExam);
                save();
            }
            catch (Exception)
            {
                return -1;
            }
            return myExam.examID; 
        }
        /// <summary>
        /// Edits an exam
        /// Precondition: User must be an administrator and the exam must exist
        /// Postcondition: Exam information has been updated in the database
        /// Author: Aron mod. by Alma
        /// Date: 4.5.12
        /// </summary>
        public bool editExam(Exam myExam)
        {
            try
            {
                var newExam = (from e in link.Exams
                            where e.examID == myExam.examID
                            select e).First();

                newExam.name = myExam.name;
                newExam.exDesc = myExam.exDesc;
                newExam.gradeValue = myExam.gradeValue;
                

                save();

                return true;
            }
            catch (Exception)
            {
                return false;
            }
            
        }

        /// <summary>
        /// Saves changes to database
        /// Precondition:
        /// Postcondition: Database has been updated
        /// Author: Aron og Bjarmi
        /// Date: 03.05.2012
        /// </summary>
        public void save()
        {
            link.SubmitChanges();
        }

        /// <summary>
        /// Adds a question to a exam. 
        /// precondition: 
        /// postcondition
        /// </summary>
        /// <param name="question"></param>
        /// <param name="exam"></param>
        /// <returns></returns>
        public bool addQuestion(examQuestion question)
        {
            try
            {
                link.examQuestions.InsertOnSubmit(question);
                save();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Gets all questions for the given examID
        /// Author:Bjarmi
        /// </summary>
        /// <param name="examID">Id of the selected Exam</param>
        /// <returns>IQueriable collection of examQuestion</returns>
        public IQueryable<examQuestion> getExamQuestions(int examID)
        {
            var exQueList = (from q in link.examQuestions
                             where q.examID == examID
                             orderby q.qNumber ascending
                             select q);
            return exQueList;
        }

        /// <summary>
        /// Gets question by its ID
        /// Author:Bjarmi
        /// </summary>
        /// <param name="questionID">the id of the desired question</param>
        /// <returns>examQuestion with the given id(if one exists)</returns>
        public examQuestion getQuestionByID(int questionID)
        {
            var result = (from q in link.examQuestions
                          where q.qID == questionID
                          select q).First();
            return result;
        }

        /// <summary>
        /// Vistar nýjann QuestionOption inn í gagnagrunn...
        /// Precondition: optionNo má ekki vera til með qID annarstaðar í töflunni.
        /// Author: Bjarmi
        /// </summary>
        /// <param name="opt">Tekur inn heilan QuestionOption object</param>
        /// <returns>skilar bool um það hvort færsla hafi tekist.</returns>
        public bool addQuestionOption(examQuestionOption opt)
        {
            try
            {
                link.examQuestionOptions.InsertOnSubmit(opt);
                save();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Gets the next optionNo for questionOption
        /// </summary>
        /// <param name="questionID">id of the question the option is for</param>
        /// <returns>the next free optionNo value in the db</returns>
        public int getNextNumberForQuestionOption(int questionID)
        {
            int retValue = (from q in link.examQuestionOptions
                        where q.qID == questionID
                        select q).Count() + 1;


            return retValue;
        }

        public IQueryable<examQuestionOption> getOptionsForQuestion(int questionID)
        {
            var retVal = from q in link.examQuestionOptions
                         where q.qID == questionID
                         orderby q.optionNo ascending
                         select q;
            return retVal;
        }

        public ExamModel getExamForTaking(int examID)
        {
            ExamModel result = (from ex in link.Exams
                                where ex.examID == examID
                                select new ExamModel
                                {
                                    examID = examID,
                                    levelID = ex.lvlID.Value,
                                    eTitle = ex.name,
                                    exDesc = ex.exDesc,
                                    qList = new List<Question>(),
                                    gradeValue = ex.gradeValue.Value,
                                    allowComments = ex.allowComments.Value
                                }).First();

            result.qList = (from exQue in link.examQuestions
                            where exQue.examID == examID
                            select new Question
                            {
                                qID = exQue.qID,
                                qText = exQue.qText,
                                optionList = new SortedList<int, string>(),
                                answer = 0
                            }).AsEnumerable();
            foreach (var q in result.qList)
            {
                var temp = (from o in link.examQuestionOptions
                            where o.qID == q.qID
                            orderby o.optionNo ascending
                            select o);
                foreach (var item in temp)
                    q.optionList.Add(item.optionNo, item.optionValue);
            }

            return result;
        }

    }
}